
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;

public class Kalenteri {

    private ArrayList[] viikonTapahtumat;
    private final String polku;

    /**
     * Palauttaa olion tietorakenteen tapahtumille. Käytetään vain debuggauksessa.
     * @return taulukollinen arrayListejä.
     */
    public ArrayList[] getViikonTapahtumat() {
        return viikonTapahtumat;
    }

    /**
     * Asettaa viikonpäivien määrän. Käytetään vain debuggauksessa.
     * @param viikonTapahtumat
     */
    public void setViikonTapahtumat(ArrayList[] viikonTapahtumat) {
        this.viikonTapahtumat = viikonTapahtumat;
    }

    /**
     * Luo uuden Kalenteri-olion.
     * @param viikonpaivia, polku
     * @param polku
     */
    public Kalenteri(int viikonpaivia, String polku) {
        this.polku = polku;
        viikonTapahtumat = lueTiedostosta(viikonpaivia);
    }

    /**
     * Lukee polku-muuttujan osoittamasta sijainnista tapahtumat. Jos lukeminen
     * ei onnistu, niin luodaan taulukollinen tyhjiä ArrayListejä ja palautetaan
     * se.
     * @param viikonpaivia, kuinka monta viikonpäivää halutaan kalenteriin.
     * @return taulukko ArrayListejä jotka kuvaavat tapahtumat.
     */
    public ArrayList[] lueTiedostosta(int viikonpaivia) {

        ArrayList[] palautus = new ArrayList[viikonpaivia];
        try {
            ObjectInputStream lukuri = new ObjectInputStream(
                    new FileInputStream(polku));

            palautus = (ArrayList[]) lukuri.readObject();

            lukuri.close();
        } catch (Exception ex) {
            /*
            //Tiedostossa jotakin vikaa
            //=>palautetaan tyhjät ArrayList:it
            ex.printStackTrace(System.err);
            System.out.println("Ohjelman tallennustiedosto on korruptoitunut.\n" +
            "Tallennetut tiedot menetetään.");
             */
            for (int i = 0; i < palautus.length; i++) {
                palautus[i] = new ArrayList<Tapahtuma>();
            }
        }
        return palautus;
    }
    
    /**
     * Kirjoittaa tapahtumien arrayListin tiedostoon
     * @return booleanin, joka kertoo onnistuiko kirjoitus(true) vai ei(false)
     */
    public boolean kirjoitaTiedostoon(){
        try {
            ObjectOutputStream kirjoitin = new ObjectOutputStream(
                    new FileOutputStream(polku));

            kirjoitin.writeObject(viikonTapahtumat);

            kirjoitin.close();
        } catch (Exception ex) {
            return false;
        }

        return true;
    }

    /**
     * Lisää uuden tapahtuman oikeaan kohtaan kalenterissa.
     * @param lisattava, lisättävä tapahtuma.
     */
    public void lisaaTapahtuma(Tapahtuma lisattava) {

        int paiva = lisattava.getPaiva();

     /* Kommentoin tämän pois koska tämä tehdään jo lueTiedostosta-metodista
      * -mikko
      *
      if (viikonTapahtumat[paiva - 1] == null) {
            viikonTapahtumat[paiva - 1] = new ArrayList<Tapahtuma>();
        }
      */

        viikonTapahtumat[paiva - 1].add(lisattava);
        Collections.sort(viikonTapahtumat[paiva - 1]);
    }

    /**
     * Poistaa tapahtuman annetun indeksin mukaan.
     * @param poistettava, poistettavan tapahtuman indeksi.
     * @return true jos tapahtuma poistettiin, false jos annettu indeksi on
     * epäkelpo.
     */
    public boolean poistaTapahtuma(int poistettava) {

        if (poistettava < 0)
            return false;

        for (int i = 0; i < viikonTapahtumat.length; i++) {
            if (viikonTapahtumat[i].size() > poistettava) {
                viikonTapahtumat[i].remove(poistettava);
                return true;
            } else {
                poistettava -= viikonTapahtumat[i].size();
            }
        }

        return false;

    }

    /**
     * Palauttaa tapahtumat String-taulukkona siten että jokainen taulukon
     * alkio edustaa yhden päivän tapahtumia. Metodin parametri tulostaIndeksit
     * kertoo halutaanko jokaisen tapahtuman eteen lisätä sen indeksi. Tätä tarvitaan
     * esimerkiksi tapahtumien poiston yhteydessä.
     * @param tulostaIndeksit, kertoo halutaanko Stringien eteen liittää tapahtuman
     * indeksi.
     * @return taulukko Stringejä jotka kuvaavat tapahtumat.
     */
    public String[] getTapahtumat(boolean tulostaIndeksit) {
        
        // jos halutaan poistettavat niin numeroidaan jokainen tapahtuma.
        int indeksi = 1;

        String[] palautus = new String[viikonTapahtumat.length];
        for (int i = 0; i < palautus.length; i++) {
            palautus[i] = "";
        }

        for (int i = 0; i < viikonTapahtumat.length; i++) {
            for (int j = 0; j < viikonTapahtumat[i].size(); j++) {

                Tapahtuma kasiteltava = (Tapahtuma) viikonTapahtumat[i].get(j);

                if (tulostaIndeksit) {
                    palautus[i] += indeksi + ". " + kasiteltava + "\n";
                    indeksi++;
                } else {
                    palautus[i] += viikonTapahtumat[i].get(j) + "\n";
                }
            }
        }

        return palautus;
    }

    /**
     * Sylkee kasaan kauhean näköisen testidata-tiedoston
     * @param polku polku, jonne tiedosto tungetaan
     * @param paivia viikonpäivien määrä, jonka mukaan tiedosto kirjoitetaan
     */
    public static void generoiTestiTiedosto(String polku, int paivia) {

        try {
            ObjectOutputStream kirjoitin = new ObjectOutputStream(
                    new FileOutputStream(polku));

            ArrayList[] ulos = new ArrayList[paivia];

            for (int i = 0; i < paivia; i++) {
                ulos[i] = new ArrayList<Tapahtuma>();
            }

            Tapahtuma t;
            boolean b;
            int k;

            for (int i = 0; i < 100; i++) {
                k = (int) ((Math.random() * 10) % ulos.length);
                t = new Tapahtuma(5);
                t.setAlkuAika((int) ((Math.random() * 100) % 24));
                t.setLoppuAika((int) ((Math.random() * 100) % 24));
                t.setNimi("nimi on " + -i);
                b = t.setPaiva(k);
                t.setSijainti("ja paikassa " + i);

                if(b)
                    ulos[t.getPaiva()].add(t);
            }

            kirjoitin.writeObject(ulos);
            kirjoitin.close();

        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }
}

